home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gawk / gawk213b.zoo / test / iop.c < prev    next >
C/C++ Source or Header  |  1991-05-05  |  5KB  |  233 lines

  1. /*
  2.  * iop.c - do i/o related things.
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. #ifndef atarist
  29. #define INVALID_HANDLE (-1)
  30. #else
  31. #include <stddef.h>
  32. #include <fcntl.h>
  33. #define INVALID_HANDLE  (__SMALLEST_VALID_HANDLE - 1)
  34. #endif  /* atarist */
  35.  
  36.  
  37. #ifdef TEST
  38. int bufsize = 8192;
  39. #endif
  40.  
  41. int
  42. optimal_bufsize(fd)
  43. int fd;
  44. {
  45.     struct stat stb;
  46.  
  47.     /*
  48.      * System V doesn't have the file system block size in the
  49.      * stat structure. So we have to make some sort of reasonable
  50.      * guess. We use stdio's BUFSIZ, since that is what it was
  51.      * meant for in the first place.
  52.      */
  53. #ifdef BLKSIZE_MISSING
  54. #define    DEFBLKSIZE    BUFSIZ
  55. #else
  56. #define DEFBLKSIZE    (stb.st_blksize ? stb.st_blksize : BUFSIZ)
  57. #endif
  58.  
  59. #ifdef TEST
  60.     return bufsize;
  61. #endif
  62. #ifndef atarist
  63.     if (isatty(fd))
  64. #else
  65.     /*
  66.      * On ST redirected stdin does not have a name attached
  67.      * (this could be hard to do to) and fstat would fail
  68.      */
  69.     if (0 == fd || isatty(fd))
  70. #endif  /*atarist */
  71.         return BUFSIZ;
  72.     if (fstat(fd, &stb) == -1)
  73.         fatal("can't stat fd %d (%s)", fd, strerror(errno));
  74.     if (lseek(fd, 0L, 0) == -1)
  75.         return DEFBLKSIZE;
  76.     return (stb.st_size < DEFBLKSIZE ? stb.st_size : DEFBLKSIZE);
  77. }
  78.  
  79. IOBUF *
  80. iop_alloc(fd)
  81. int fd;
  82. {
  83.     IOBUF *iop;
  84.  
  85.     if (fd == INVALID_HANDLE)
  86.         return NULL;
  87.     emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
  88.     iop->flag = 0;
  89.     if (isatty(fd))
  90.         iop->flag |= IOP_IS_TTY;
  91.     iop->size = optimal_bufsize(fd);
  92.     errno = 0;
  93.     iop->fd = fd;
  94.     emalloc(iop->buf, char *, iop->size + 2, "iop_alloc");
  95.     iop->end = iop->off = iop->buf;
  96.     iop->secsiz = iop->size < BUFSIZ ? iop->size : BUFSIZ;
  97.     emalloc(iop->secbuf, char *, iop->secsiz+2, "iop_alloc");
  98.     iop->cnt = -1;
  99.     return iop;
  100. }
  101.  
  102. int
  103. get_a_record(out, iop, rs)
  104. char **out;
  105. IOBUF *iop;
  106. register int rs;
  107. {
  108.     register char *bp = iop->off;
  109.     register char *end_data = iop->end;    /* end of current data read */
  110.     char *end_buf = iop->buf + iop->size;    /* end of input buffer */
  111.     char *start = iop->off;            /* beginning of record */
  112.     char *offset = iop->secbuf;        /* end of data in secbuf */
  113.     size_t size;
  114.  
  115.     if (iop->cnt == 0)
  116.         return EOF;
  117.  
  118.     /* set up sentinels */
  119.     if (rs == 0) {
  120.         *end_data = *(end_data+1) = '\n';
  121.         *end_buf = *(end_buf+1) = '\n';
  122.     } else
  123.         *end_data = *end_buf = rs;
  124.  
  125.     for (;;) {    /* break on end of record, read error or EOF */
  126.  
  127.         if (bp == end_data) {
  128.             if (bp == end_buf) {    /* record spans buffer end */
  129. #ifdef atarist
  130. #define P_DIFF ptrdiff_t
  131. #else
  132. #define P_DIFF int
  133. #endif
  134. #define    COPY_TO_SECBUF    { \
  135.                 P_DIFF oldlen = offset - iop->secbuf; \
  136.                 P_DIFF newlen = bp - start; \
  137.                                  \
  138.                 if (iop->secsiz < oldlen + newlen) { \
  139.                     erealloc(iop->secbuf, char *, \
  140.                         oldlen+newlen, "get_record"); \
  141.                     offset = iop->secbuf + oldlen; \
  142.                 } \
  143.                 memcpy(offset, start, newlen); \
  144.                 offset += newlen; \
  145.             }
  146.                 COPY_TO_SECBUF
  147.                 start = bp = iop->buf;
  148.                 size = iop->size;
  149.             } else
  150.                 size = end_buf - bp;
  151.             iop->cnt = read(iop->fd, bp, size);
  152.             if (iop->cnt == -1)
  153.                 fatal("error reading input");
  154.             else if (iop->cnt == 0) {
  155.                 break;
  156.             } else {
  157.                 end_data = bp + iop->cnt;
  158.                 if (rs == 0 && *bp == '\n'
  159.                     && offset > iop->secbuf
  160.                     && *(offset-1) == '\n') {
  161.                     bp++;
  162.                     break;
  163.                 }
  164.                 if (rs == 0) {
  165.                     *end_data = *(end_data+1) = '\n';
  166.                     *end_buf = *(end_buf+1) = '\n';
  167.                 } else
  168.                     *end_data = rs;
  169.             }
  170.         }
  171.         if (rs == 0) {
  172.             for (;;) {
  173.                 if (*bp++ == '\n' && *bp == '\n') {
  174.                     bp++;
  175.                     break;
  176.                 }
  177.             }
  178.         } else
  179.             while (*bp++ != rs)
  180.                 ;
  181.         if (bp <= end_data)    /* end of record */
  182.             break;
  183.         bp = end_data;
  184.     }
  185.     if (offset == iop->secbuf && start == bp && iop->cnt == 0) {
  186.         *out = start;
  187.         return EOF;
  188.     }
  189.     iop->off = bp;
  190.     iop->end = end_data;
  191.     if (offset != iop->secbuf) {
  192.         if (start != bp)
  193.             COPY_TO_SECBUF
  194.         start = iop->secbuf;
  195.         bp = offset;
  196.     }
  197.     if (rs == 0) {
  198.         if (*--bp == '\n') {
  199.             *bp = '\0';
  200.             if (*--bp == '\n')
  201.                 *bp = '\0';
  202.             else
  203.                 bp++;
  204.         } else
  205.             bp++;
  206.     } else if (*--bp == rs)
  207.         ;
  208.     else
  209.         bp++;
  210.     *bp = '\0';
  211.     *out = start;
  212.     return bp - start;
  213. }
  214.  
  215. #ifdef TEST
  216. main(argc, argv)
  217. int argc;
  218. char *argv[];
  219. {
  220.     IOBUF *iop;
  221.     char *out;
  222.     int cnt;
  223.  
  224.     if (argc > 1)
  225.         bufsize = atoi(argv[1]);
  226.     iop = iop_alloc(0);
  227.     while ((cnt = get_a_record(&out, iop, 0)) > 0) {
  228.         fwrite(out, 1, cnt, stdout);
  229.         fwrite("\n", 1, 1, stdout);
  230.     }
  231. }
  232. #endif
  233.